package com.bsj.sipgateway.sip.transmit.request;

import gov.nist.javax.sip.SipStackImpl;
import gov.nist.javax.sip.header.Via;
import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.message.SIPResponse;
import gov.nist.javax.sip.stack.SIPServerTransaction;

import javax.sip.*;
import javax.sip.address.Address;
import javax.sip.address.AddressFactory;
import javax.sip.address.SipURI;
import javax.sip.header.ContentTypeHeader;
import javax.sip.header.ExpiresHeader;
import javax.sip.header.HeaderFactory;
import javax.sip.header.ViaHeader;
import javax.sip.message.MessageFactory;
import javax.sip.message.Request;
import javax.sip.message.Response;
import java.text.ParseException;

/**    
 * @Description:处理接收IPCamera发来的SIP协议请求消息
 * @author bsj-chenjunkang
 * @date 2022/8/24
 */
public abstract class SIPRequestAbstractProcessor implements ISIPRequestProcessor {

	protected RequestEvent evt;
	
	private SipProvider tcpSipProvider;
	
	private SipProvider udpSipProvider;
	
	@Override
	public void process() {
		this.process(evt);
	}

	public abstract void process(RequestEvent evt);

	/**
	 * sip响应时设置设备的外网端口
	 * @param evt
	 * @param response
	 * @throws ParseException
	 */
	public void setRport(RequestEvent evt, Response response) throws ParseException {
		SIPRequest sipRequest = (SIPRequest) evt.getRequest();
		SIPResponse sipResponse = (SIPResponse)response;
		Via via = sipResponse.getTopmostVia();
		via.setParameter(Via.RPORT, String.valueOf(sipRequest.getPeerPacketSourcePort()));
	}
	
	public ServerTransaction getServerTransaction(RequestEvent evt) {
		Request request = evt.getRequest();
		ServerTransaction serverTransaction = evt.getServerTransaction();
		// 判断TCP还是UDP
		boolean isTcp = false;
		ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
		String transport = reqViaHeader.getTransport();
		if (transport.equals("TCP")) {
			isTcp = true;
		}

		if (serverTransaction == null) {
			try {
				if (isTcp) {
					SipStackImpl stack = (SipStackImpl)tcpSipProvider.getSipStack();
					serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest)request, true);
					if (serverTransaction == null) {
						serverTransaction = tcpSipProvider.getNewServerTransaction(request);
					}
				} else {
					SipStackImpl stack = (SipStackImpl)udpSipProvider.getSipStack();
					serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest)request, true);
					if (serverTransaction == null) {
						serverTransaction = udpSipProvider.getNewServerTransaction(request);
					}
				}
			} catch (TransactionAlreadyExistsException | TransactionUnavailableException e) {
				e.printStackTrace();
			}
		}
		return serverTransaction;
	}
	
	public AddressFactory getAddressFactory() {
		try {
			return SipFactory.getInstance().createAddressFactory();
		} catch (PeerUnavailableException e) {
			e.printStackTrace();
		}
		return null;
	}

	public HeaderFactory getHeaderFactory() {
		try {
			return SipFactory.getInstance().createHeaderFactory();
		} catch (PeerUnavailableException e) {
			e.printStackTrace();
		}
		return null;
	}

	public MessageFactory getMessageFactory() {
		try {
			return SipFactory.getInstance().createMessageFactory();
		} catch (PeerUnavailableException e) {
			e.printStackTrace();
		}
		return null;
	}

	/***
	 * 回复状态码
	 * 100 trying
	 * 200 OK
	 * 400
	 * 404
	 * @param evt
	 * @throws SipException
	 * @throws InvalidArgumentException
	 * @throws ParseException
	 */
	public void responseAck(RequestEvent evt, int statusCode) throws SipException, InvalidArgumentException, ParseException {
		Response response = getMessageFactory().createResponse(statusCode, evt.getRequest());
		//设置设备的外网端口
		setRport(evt, response);
		getServerTransaction(evt).sendResponse(response);
	}

	/***
	 * 回复200 OK
	 * @param evt
	 * @throws SipException
	 * @throws InvalidArgumentException
	 * @throws ParseException
	 */
	public void responseAck(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException {
		Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
		//设置设备的外网端口
		setRport(evt, response);
		getServerTransaction(evt).sendResponse(response);
	}


	/**
	 * 回复带sdp的200
	 * @param evt
	 * @param sdp
	 * @throws SipException
	 * @throws InvalidArgumentException
	 * @throws ParseException
	 */
	public void responseSdpAck(RequestEvent evt, String sdp) throws SipException, InvalidArgumentException, ParseException {
		Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
		SipFactory sipFactory = SipFactory.getInstance();
		ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
		response.setContent(sdp, contentTypeHeader);
		//设置设备的外网端口
		setRport(evt, response);
		// 兼容国标中的使用编码@域名作为RequestURI的情况
		SipURI sipURI = (SipURI)evt.getRequest().getRequestURI();
	/*	if (sipURI.getPort() == -1) {
			sipURI = sipFactory.createAddressFactory().createSipURI(platform.getServerGBId(),  platform.getServerIP()+":"+platform.getServerPort());
		}
		logger.debug("responseSdpAck SipURI: {}:{}", sipURI.getHost(), sipURI.getPort());
*/
		Address concatAddress = sipFactory.createAddressFactory().createAddress(
				sipFactory.createAddressFactory().createSipURI(sipURI.getUser(),  sipURI.getHost()+":"+sipURI.getPort()
				));
		response.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
		getServerTransaction(evt).sendResponse(response);
	}

	/**
	 * 回复带xml的200
	 * @param evt
	 * @param xml
	 * @throws SipException
	 * @throws InvalidArgumentException
	 * @throws ParseException
	 */
	public Response responseXmlAck(RequestEvent evt, String xml) throws SipException, InvalidArgumentException, ParseException {
		Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
		SipFactory sipFactory = SipFactory.getInstance();
		ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
		response.setContent(xml, contentTypeHeader);
		//设置设备的外网端口
		setRport(evt, response);
		// 兼容国标中的使用编码@域名作为RequestURI的情况
		SipURI sipURI = (SipURI)evt.getRequest().getRequestURI();
		/*if (sipURI.getPort() == -1) {
			sipURI = sipFactory.createAddressFactory().createSipURI(platform.getServerGBId(),  platform.getServerIP()+":"+platform.getServerPort());
		}
		logger.debug("responseXmlAck SipURI: {}:{}", sipURI.getHost(), sipURI.getPort());*/

		Address concatAddress = sipFactory.createAddressFactory().createAddress(
				sipFactory.createAddressFactory().createSipURI(sipURI.getUser(),  sipURI.getHost()+":"+sipURI.getPort()
				));
		response.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
		response.addHeader(evt.getRequest().getHeader(ExpiresHeader.NAME));
		getServerTransaction(evt).sendResponse(response);
		return response;
	}

	public RequestEvent getRequestEvent() {
		return evt;
	}

	public void setRequestEvent(RequestEvent evt) {
		this.evt = evt;
	}

	public SipProvider getTcpSipProvider() {
		return tcpSipProvider;
	}

	public void setTcpSipProvider(SipProvider tcpSipProvider) {
		this.tcpSipProvider = tcpSipProvider;
	}

	public SipProvider getUdpSipProvider() {
		return udpSipProvider;
	}

	public void setUdpSipProvider(SipProvider udpSipProvider) {
		this.udpSipProvider = udpSipProvider;
	}


	
	
}
